package com.lcn.netty.utils;

import com.lcn.pojo.netty.NettyServerNode;
import com.lcn.utils.JsonUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.recipes.locks.InterProcessReadWriteLock;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.data.Stat;

import java.util.List;

@Slf4j
public class ZookeeperRegister {

    /**
     * 将netty注册到zookeeper
     *
     * @param ip netty服务器主机地址
     * @param port netty服务器端口号
     * @param nodeName 注册后的节点名称
     */
    public static void registerNettyServer(String ip, Integer port, String nodeName) throws Exception {
        CuratorFramework zkClient = CuratorUtils.getClient();
        String path = "/" + nodeName;
        Stat stat = zkClient.checkExists().forPath(path);
        // 没节点则创建节点
        if (stat == null) {
            zkClient.create()
                    .creatingParentsIfNeeded() // 递归创建
                    .withMode(CreateMode.PERSISTENT) // 永久节点
                    .forPath(path);
        }
        // 创建[临时顺序]子节点
        String tmpPath = path + "/im-";
        NettyServerNode nettyServerNode = new NettyServerNode();
        nettyServerNode.setIp(ip);
        nettyServerNode.setPort(port);
        String jsonTmp = JsonUtils.objectToJson(nettyServerNode);
        zkClient.create()
                .withMode(CreateMode.EPHEMERAL_SEQUENTIAL)
                .forPath(tmpPath, jsonTmp.getBytes());
    }

    public static String getHost() {
        return "127.0.0.1";
    }

    /**
     * 累加zookeeper中的netty在线人数
     */
    public static void incrementOnlineCounts(NettyServerNode nettyServerNode) throws Exception {
        dealOnlineCounts(nettyServerNode, 1);
    }

    /**
     * 累减zookeeper中的netty在线人数
     */
    public static void decrementOnlineCounts(NettyServerNode nettyServerNode) throws Exception {
        dealOnlineCounts(nettyServerNode, -1);
    }

    /**
     * 处理zookeeper中的netty在线人数
     *
     * @param nettyServerNode
     * @param count
     */
    public static void dealOnlineCounts(NettyServerNode nettyServerNode, Integer count) throws Exception {
        String rootPath = "/server-list";
        CuratorFramework zkClient = CuratorUtils.getClient();

        // zk分布式锁
        InterProcessReadWriteLock lock = new InterProcessReadWriteLock(zkClient, "/rw-lock");

        lock.writeLock().acquire(); // 加锁

        try {
            // 获取所有节点
            List<String> nodeList = zkClient.getChildren().forPath(rootPath);
            for (String node : nodeList) {
                String targetPath = rootPath + "/" + node;
                String json = new String(zkClient.getData().forPath(targetPath));
                NettyServerNode targetNode = JsonUtils.jsonToPojo(json, NettyServerNode.class);
                if ( targetNode.getIp().equals(nettyServerNode.getIp() )
                        && ( targetNode.getPort().equals(nettyServerNode.getPort())) ) {
                    targetNode.setOnlineCount(targetNode.getOnlineCount() + count);
                    zkClient.setData().forPath(targetPath, JsonUtils.objectToJson(targetNode).getBytes());
                }
            }
        } finally {
            lock.writeLock().release(); // 释放锁
        }

    }

}
